package project.tool4nat.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import project.tool4nat.client.handler.ClientTunnelHandler;
import project.tool4nat.common.*;

public class ClientStarter implements Starter {

    private final static Logger logger = LoggerFactory.getLogger(ClientStarter.class);

    private EventLoopGroup group = new NioEventLoopGroup();

    private void connectNatServer() throws InterruptedException {
        logger.info("connect nat server on host {}, port {}", Config.SERVER_HOST, Config.SERVER_PORT);
        logger.info("listen request for host {}, port {}", Config.CONTENT_SERVER_HOST, Config.CONTENT_SERVER_PORT);
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline()
                                .addLast(new DataPackDecoder(1024 * 1024 * 3, 0, 4))
                                .addLast(new DataPackEncoder())
                                .addLast(new ClientTunnelHandler(group));
                    }
                })
                .connect(Config.SERVER_HOST, Config.SERVER_PORT)
                .addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            DataPack dataPack = new DataPack();
                            dataPack.setType(Constants.TYPE_CONNECT);
                            future.channel().writeAndFlush(dataPack);
                        } else {
                            shutdown();
                        }
                    }
                });
//                .sync().channel().closeFuture().sync();
    }

    @Override
    public void startup() throws Exception {
        connectNatServer();
    }

    @Override
    public void shutdown() {
        group.shutdownGracefully();
    }

    public static void main(String[] args) {
        Starter starter = new ClientStarter();
        try {
            starter.startup();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            starter.shutdown();
        }
    }
}
